home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -screenplay- / otherstuff / inform_lib610 / verblibm.h < prev   
Text File  |  1999-11-29  |  61KB  |  2,019 lines

  1. ! ----------------------------------------------------------------------------
  2. !  VERBLIBM:  Core of standard verbs library.
  3. !
  4. !  Supplied for use with Inform 6                         Serial number 991106
  5. !                                                                 Release 6/10
  6. !  (c) Graham Nelson 1993, 1994, 1995, 1996, 1997, 1998, 1999
  7. !      but freely usable (see manuals)
  8. ! ----------------------------------------------------------------------------
  9.  
  10. #IFDEF MODULE_MODE;
  11. Constant DEBUG;
  12. Constant Grammar__Version2;
  13. Include "linklpa";
  14. Include "linklv";
  15. #ENDIF;
  16.  
  17. System_file;
  18.  
  19. ! ----------------------------------------------------------------------------
  20.  
  21. [ Banner i;
  22.    if (Story ~= 0)
  23.    {
  24. #IFV5; style bold; #ENDIF;
  25.    print (string) Story;
  26. #IFV5; style roman; #ENDIF;
  27.    }
  28.    if (Headline ~= 0)
  29.        print (string) Headline;
  30.    print "Release ", (0-->1) & $03ff, " / Serial number ";
  31.    for (i=18:i<24:i++) print (char) 0->i;
  32.    print " / Inform v"; inversion;
  33.    print " Library ", (string) LibRelease, " ";
  34. #ifdef STRICT_MODE;
  35.    print "S";
  36. #endif;
  37. #ifdef INFIX;
  38.    print "X";
  39. #ifnot;
  40. #ifdef DEBUG;
  41.    print "D";
  42. #endif;
  43. #endif;
  44.    new_line;
  45. ];
  46.  
  47. [ VersionSub;
  48.   Banner();
  49.   if (standard_interpreter > 0)
  50.       print "Standard interpreter ",
  51.           standard_interpreter/256, ".", standard_interpreter%256,
  52.           " (", 0->$1e, (char) 0->$1f, ") / ";
  53.   else print "Interpreter ", 0->$1e, " Version ", (char) 0->$1f, " / ";
  54.   print "Library serial number ", (string) LibSerial, "^";
  55. #IFDEF LanguageVersion;
  56.   print (string) LanguageVersion, "^";
  57. #ENDIF;
  58. ];
  59.  
  60. [ RunTimeError n p1 p2;
  61. #IFDEF DEBUG;
  62.   print "** Library error ", n, " (", p1, ",", p2, ") **^** ";
  63.   switch(n)
  64.   {   1: print "preposition not found (this should not occur)";
  65.       2: print "Property value not routine or string: ~",
  66.                (property) p2, "~ of ~", (name) p1, "~ (", p1, ")";
  67.       3: print "Entry in property list not routine or string: ~",
  68.                (property) p2, "~ list of ~", (name) p1, "~ (", p1, ")";
  69.       4: print "Too many timers/daemons are active simultaneously.  The
  70.                 limit is the library constant MAX_TIMERS (currently ",
  71.                 MAX_TIMERS, ") and should be increased";
  72.       5: print "Object ~", (name) p1, "~ has no ~time_left~ property";
  73.       7: print "The object ~", (name) p1, "~ can only be used as a player
  74.                 object if it has the ~number~ property";
  75.       8: print "Attempt to take random entry from an empty table array";
  76.       9: print p1, " is not a valid direction property number";
  77.       10: print "The player-object is outside the object tree";
  78.       11: print "The room ~", (name) p1, "~ has no ~description~ property";
  79.       12: print "Tried to set a non-existent pronoun using SetPronoun";
  80.       13: print "A 'topic' token can only be followed by a preposition";
  81.       default: print "(unexplained)";
  82.   }
  83.   " **";
  84. #IFNOT;
  85.   "** Library error ", n, " (", p1, ",", p2, ") **";
  86. #ENDIF;
  87. ];
  88.  
  89. ! ----------------------------------------------------------------------------
  90. !  The WriteListFrom routine, a flexible object-lister taking care of
  91. !  plurals, inventory information, various formats and so on.  This is used
  92. !  by everything in the library which ever wants to list anything.
  93. !
  94. !  If there were no objects to list, it prints nothing and returns false;
  95. !  otherwise it returns true.
  96. !
  97. !  o is the object, and style is a bitmap, whose bits are given by:
  98. ! ----------------------------------------------------------------------------
  99.  
  100. Constant NEWLINE_BIT    1;    !  New-line after each entry
  101. Constant INDENT_BIT     2;    !  Indent each entry by depth
  102. Constant FULLINV_BIT    4;    !  Full inventory information after entry
  103. Constant ENGLISH_BIT    8;    !  English sentence style, with commas and and
  104. Constant RECURSE_BIT   16;    !  Recurse downwards with usual rules
  105. Constant ALWAYS_BIT    32;    !  Always recurse downwards
  106. Constant TERSE_BIT     64;    !  More terse English style
  107. Constant PARTINV_BIT  128;    !  Only brief inventory information after entry
  108. Constant DEFART_BIT   256;    !  Use the definite article in list
  109. Constant WORKFLAG_BIT 512;    !  At top level (only), only list objects
  110.                               !  which have the "workflag" attribute
  111. Constant ISARE_BIT   1024;    !  Print " is" or " are" before list
  112. Constant CONCEAL_BIT 2048;    !  Omit objects with "concealed" or "scenery":
  113.                               !  if WORKFLAG_BIT also set, then does _not_
  114.                               !  apply at top level, but does lower down
  115. Constant NOARTICLE_BIT 4096;  !  Print no articles, definite or not
  116.  
  117. [ NextEntry o odepth;
  118.   for(::)
  119.   {   o=sibling(o);
  120.       if (o==0) return 0;
  121.       if (lt_value ~=0 && o.list_together~=lt_value) continue;
  122.       if (c_style & WORKFLAG_BIT ~= 0 && odepth==0 && o hasnt workflag)
  123.           continue;
  124.       if (c_style & CONCEAL_BIT ~= 0 && (o has concealed || o has scenery))
  125.           continue;
  126.       return o;
  127.   }
  128. ];
  129.  
  130. [ WillRecurs o;
  131.   if (c_style & ALWAYS_BIT ~= 0) rtrue;
  132.   if (c_style & RECURSE_BIT == 0) rfalse;
  133.   if (o has transparent
  134.       || o has supporter
  135.       || (o has container && o has open)) rtrue;
  136.   rfalse;
  137. ];
  138.  
  139. [ ListEqual o1 o2;
  140.   if (child(o1)~=0 && WillRecurs(o1)~=0) rfalse;
  141.   if (child(o2)~=0 && WillRecurs(o2)~=0) rfalse;
  142.  
  143.   if (c_style & (FULLINV_BIT + PARTINV_BIT) ~= 0)
  144.   {   if ((o1 hasnt worn && o2 has worn)
  145.           || (o2 hasnt worn && o1 has worn)) rfalse;
  146.       if ((o1 hasnt light && o2 has light)
  147.           || (o2 hasnt light && o1 has light)) rfalse;
  148.   }
  149.  
  150.   return Identical(o1,o2);
  151. ];
  152.  
  153. [ SortTogether obj value;
  154. !  print "Sorting together possessions of ",
  155. !         (object) obj, " by value ", value, "^";
  156. !  for (x=child(obj):x~=0:x=sibling(x))
  157. !      print (the) x, " no: ", x, " lt: ", x.list_together, "^";
  158.   while (child(obj)~=0)
  159.   {   if (child(obj).list_together~=value) move child(obj) to out_obj;
  160.       else move child(obj) to in_obj;
  161.   }
  162.   while (child(in_obj)~=0)
  163.       move child(in_obj) to obj;
  164.   while (child(out_obj)~=0)
  165.       move child(out_obj) to obj;
  166. ];
  167.  
  168. [ SortOutList obj i k l;
  169. !  print "^^Sorting out list from ", (name) obj, "^  ";
  170. !  for (i=child(location):i~=0:i=sibling(i))
  171. !      print (name) i, " --> ";
  172. !  new_line;
  173.  .AP_SOL;
  174.   for (i=obj:i~=0:i=sibling(i))
  175.   {   k=i.list_together;
  176.       if (k~=0)
  177.       {   ! print "Scanning ", (name) i, " with lt=", k, "^";
  178.           for (i=sibling(i):i~=0 && i.list_together==k:) i=sibling(i);
  179.               if (i==0) rfalse;
  180.           !print "First not in block is ", (name) i,
  181.           ! " with lt=", i.list_together, "^";
  182.           for (l=sibling(i):l~=0:l=sibling(l))
  183.               if (l.list_together==k)
  184.               {   SortTogether(parent(obj), k);
  185. !  print "^^After ST:^  ";
  186. !  for (i=child(location):i~=0:i=sibling(i))
  187. !      print (name) i, " --> ";
  188. !  new_line;
  189.                   obj = child(parent(obj));
  190.                   jump AP_SOL;
  191.               }
  192.       }
  193.   }
  194. ];
  195.  
  196. [ Print__Spaces n;         ! To avoid a bug occurring in Inform 6.01 to 6.10
  197.   if (n==0) return; spaces n; ];
  198.  
  199. [ WriteListFrom o style depth;
  200.   if (o==child(parent(o)))
  201.   {   SortOutList(o); o=child(parent(o)); }
  202.   c_style=style;
  203.   wlf_indent=0; WriteListR(o,depth);
  204.   rtrue;
  205. ];
  206.  
  207. [ WriteListR o depth stack_pointer  classes_p sizes_p i j k k2 l m n q senc mr;
  208.  
  209.   if (depth>0 && o==child(parent(o)))
  210.   {   SortOutList(o); o=child(parent(o)); }
  211.   for (::)
  212.   {   if (o==0) rfalse;
  213.       if (c_style & WORKFLAG_BIT ~= 0 && depth==0 && o hasnt workflag)
  214.       {   o = sibling(o); continue; }
  215.       if (c_style & CONCEAL_BIT ~= 0
  216.           && (o has concealed || o has scenery))
  217.       {   o=sibling(o); continue; }
  218.       break;
  219.   }
  220.  
  221.   classes_p = match_classes + stack_pointer;
  222.   sizes_p   = match_list + stack_pointer;
  223.  
  224.   for (i=o,j=0:i~=0 && (j+stack_pointer)<128:i=NextEntry(i,depth),j++)
  225.   {   classes_p->j=0;
  226.       if (i.plural~=0) k++;
  227.   }
  228.  
  229.   if (c_style & ISARE_BIT ~= 0)
  230.   {   if (j==1 && o hasnt pluralname)
  231.           print (string) IS__TX; else print (string) ARE__TX;
  232.       if (c_style & NEWLINE_BIT ~= 0) print ":^"; else print (char) ' ';
  233.       c_style = c_style - ISARE_BIT;
  234.   }
  235.  
  236.   stack_pointer = stack_pointer+j+1;
  237.  
  238.   if (k<2) jump EconomyVersion;   ! It takes two to plural
  239.   n=1;
  240.   for (i=o,k=0:k<j:i=NextEntry(i,depth),k++)
  241.       if (classes_p->k==0)
  242.       {   classes_p->k=n; sizes_p->n=1;
  243.           for (l=NextEntry(i,depth), m=k+1:l~=0 && m<j:
  244.                l=NextEntry(l,depth), m++)
  245.               if (classes_p->m==0 && i.plural~=0 && l.plural~=0)
  246.               {   if (ListEqual(i,l)==1)
  247.                   {   sizes_p->n = sizes_p->n + 1;
  248.                       classes_p->m = n;
  249.                   }
  250.               }
  251.           n++;
  252.       }
  253.   n--;
  254.  
  255.   for (i=1, j=o, k=0: i<=n: i++, senc++)
  256.   {   while (((classes_p->k) ~= i)
  257.              && ((classes_p->k) ~= -i)) { k++; j=NextEntry(j,depth); }
  258.       m=sizes_p->i;
  259.       if (j==0) mr = 0;
  260.       else
  261.       {   if (j.list_together~=0 or lt_value
  262.               && ZRegion(j.list_together)==2 or 3
  263.               && j.list_together==mr) senc--;
  264.           mr=j.list_together;
  265.       }
  266.   }
  267.   senc--;
  268.  
  269.   for (i=1, j=o, k=0, mr=0: senc>=0: i++, senc--)
  270.   {   while (((classes_p->k) ~= i)
  271.              && ((classes_p->k) ~= -i)) { k++; j=NextEntry(j,depth); }
  272.       if (j.list_together~=0 or lt_value)
  273.       {   if (j.list_together==mr) { senc++; jump Omit_FL2; }
  274.           k2=NextEntry(j,depth);
  275.           if (k2==0 || k2.list_together~=j.list_together) jump Omit_WL2;
  276.           k2=ZRegion(j.list_together);
  277.           if (k2==2 or 3)
  278.           {   q=j; listing_size=1; l=k; m=i;
  279.               while (m<n && q.list_together==j.list_together)
  280.               {   m++;
  281.                   while (((classes_p->l) ~= m)
  282.                          && ((classes_p->l) ~= -m))
  283.                   {   l++; q=NextEntry(q,depth); }
  284.                   if (q.list_together==j.list_together) listing_size++;
  285.               }
  286. !              print " [", listing_size, "] ";
  287.               if (listing_size==1) jump Omit_WL2;
  288.               if (c_style & INDENT_BIT ~= 0)
  289.                   Print__Spaces(2*(depth+wlf_indent));
  290.               if (k2==3)
  291.               {   q=0; for (l=0:l<listing_size:l++) q=q+sizes_p->(l+i);
  292.                   EnglishNumber(q); print " ";
  293.                   print (string) j.list_together;
  294.                   if (c_style & ENGLISH_BIT ~= 0) print " (";
  295.                   if (c_style & INDENT_BIT ~= 0) print ":^";
  296.               }
  297.               q=c_style;
  298.               if (k2~=3)
  299.               {   inventory_stage=1;
  300.                   parser_one=j; parser_two=depth+wlf_indent;
  301.                   if (RunRoutines(j,list_together)==1) jump Omit__Sublist2;
  302.               }
  303.  
  304.               @push lt_value; @push listing_together; @push listing_size;
  305.               lt_value=j.list_together; listing_together=j; wlf_indent++;
  306.               WriteListR(j,depth,stack_pointer); wlf_indent--;
  307.               @pull listing_size; @pull listing_together; @pull lt_value;
  308.  
  309.               if (k2==3)
  310.               {   if (q & ENGLISH_BIT ~= 0) print ")";
  311.               }
  312.               else
  313.               {   inventory_stage=2;
  314.                   parser_one=j; parser_two=depth+wlf_indent;
  315.                   RunRoutines(j,list_together);
  316.               }
  317.              .Omit__Sublist2;
  318.               if (q & NEWLINE_BIT ~= 0 && c_style & NEWLINE_BIT == 0)
  319.                   new_line;
  320.               c_style=q;
  321.               mr=j.list_together;
  322.               jump Omit_EL2;
  323.           }
  324.       }
  325.  
  326.      .Omit_WL2;
  327.       if (WriteBeforeEntry(j,depth,-senc)==1) jump Omit_FL2;
  328.       if (sizes_p->i == 1)
  329.       {   if (c_style & NOARTICLE_BIT ~= 0) print (name) j;
  330.           else
  331.           {   if (c_style & DEFART_BIT ~= 0) print (the) j; else print (a) j;
  332.           }
  333.       }
  334.       else
  335.       {   if (c_style & DEFART_BIT ~= 0)
  336.               PrefaceByArticle(j, 1, sizes_p->i);
  337.           print (number) sizes_p->i, " ";
  338.           PrintOrRun(j,plural,1);
  339.       }
  340.       WriteAfterEntry(j,depth,stack_pointer);
  341.  
  342.      .Omit_EL2;
  343.       if (c_style & ENGLISH_BIT ~= 0)
  344.       {   if (senc==1) print (string) AND__TX;
  345.           if (senc>1) print ", ";
  346.       }
  347.      .Omit_FL2;
  348.   }
  349.   rtrue;
  350.  
  351.   .EconomyVersion;
  352.  
  353.   n=j;
  354.  
  355.   for (i=1, j=o: i<=n: j=NextEntry(j,depth), i++, senc++)
  356.   {   if (j.list_together~=0 or lt_value
  357.           && ZRegion(j.list_together)==2 or 3
  358.           && j.list_together==mr) senc--;
  359.       mr=j.list_together;
  360.   }
  361.  
  362.   for (i=1, j=o, mr=0: i<=senc: j=NextEntry(j,depth), i++)
  363.   {   if (j.list_together~=0 or lt_value)
  364.       {   if (j.list_together==mr) { i--; jump Omit_FL; }
  365.           k=NextEntry(j,depth);
  366.           if (k==0 || k.list_together~=j.list_together) jump Omit_WL;
  367.           k=ZRegion(j.list_together);
  368.           if (k==2 or 3)
  369.           {   if (c_style & INDENT_BIT ~= 0)
  370.                   Print__Spaces(2*(depth+wlf_indent));
  371.               if (k==3)
  372.               {   q=j; l=0;
  373.                   do
  374.                   {   q=NextEntry(q,depth); l++;
  375.                   } until (q==0 || q.list_together~=j.list_together);
  376.                   EnglishNumber(l); print " ";
  377.                   print (string) j.list_together;
  378.                   if (c_style & ENGLISH_BIT ~= 0) print " (";
  379.                   if (c_style & INDENT_BIT ~= 0) print ":^";
  380.               }
  381.               q=c_style;
  382.               if (k~=3)
  383.               {   inventory_stage=1;
  384.                   parser_one=j; parser_two=depth+wlf_indent;
  385.                   if (RunRoutines(j,list_together)==1) jump Omit__Sublist;
  386.               }
  387.  
  388.               @push lt_value; @push listing_together; @push listing_size;
  389.               lt_value=j.list_together; listing_together=j; wlf_indent++;
  390.               WriteListR(j,depth,stack_pointer); wlf_indent--;
  391.               @pull listing_size; @pull listing_together; @pull lt_value;
  392.  
  393.               if (k==3)
  394.               {   if (q & ENGLISH_BIT ~= 0) print ")";
  395.               }
  396.               else
  397.               {   inventory_stage=2;
  398.                   parser_one=j; parser_two=depth+wlf_indent;
  399.                   RunRoutines(j,list_together);
  400.               }
  401.              .Omit__Sublist;
  402.               if (q & NEWLINE_BIT ~= 0 && c_style & NEWLINE_BIT == 0) new_line;
  403.               c_style=q;
  404.               mr=j.list_together;
  405.               jump Omit_EL;
  406.           }
  407.       }
  408.      .Omit_WL;
  409.       if (WriteBeforeEntry(j,depth,i-senc)==1) jump Omit_FL;
  410.       if (c_style & NOARTICLE_BIT ~= 0) print (name) j;
  411.       else
  412.       {   if (c_style & DEFART_BIT ~= 0) print (the) j; else print (a) j;
  413.       }
  414.       WriteAfterEntry(j,depth,stack_pointer);
  415.  
  416.      .Omit_EL;
  417.       if (c_style & ENGLISH_BIT ~= 0)
  418.       {   if (i==senc-1) print (string) AND__TX;
  419.           if (i<senc-1) print ", ";
  420.       }
  421.      .Omit_FL;
  422.   }
  423. ];
  424.  
  425. [ WriteBeforeEntry o depth sentencepos  flag;
  426.   if (c_style & INDENT_BIT ~= 0) Print__Spaces(2*(depth+wlf_indent));
  427.  
  428.   if (c_style & FULLINV_BIT ~= 0)
  429.   {   if (o.invent~=0)
  430.       {   inventory_stage=1;
  431.           flag=PrintOrRun(o,invent,1);
  432.           if (flag==1)
  433.           {   if (c_style & ENGLISH_BIT ~= 0)
  434.               {   if (sentencepos == -1) print (string) AND__TX;
  435.                   if (sentencepos < -1) print ", ";
  436.               }
  437.               if (c_style & NEWLINE_BIT ~= 0) new_line;
  438.           }
  439.       }
  440.   }
  441.   return flag;
  442. ];
  443.  
  444. [ WriteAfterEntry o depth stack_p  flag flag2 flag3 p comb;
  445.  
  446.   if (c_style & PARTINV_BIT ~= 0)
  447.   {   comb=0;
  448.       if (o has light && location hasnt light) comb=comb+1;
  449.       if (o has container && o hasnt open)     comb=comb+2;
  450.       if ((o has container && (o has open || o has transparent))
  451.           && (child(o)==0)) comb=comb+4;
  452.       if (comb==1) L__M(##ListMiscellany, 1, o);
  453.       if (comb==2) L__M(##ListMiscellany, 2, o);
  454.       if (comb==3) L__M(##ListMiscellany, 3, o);
  455.       if (comb==4) L__M(##ListMiscellany, 4, o);
  456.       if (comb==5) L__M(##ListMiscellany, 5, o);
  457.       if (comb==6) L__M(##ListMiscellany, 6, o);
  458.       if (comb==7) L__M(##ListMiscellany, 7, o);
  459.   }
  460.  
  461.   if (c_style & FULLINV_BIT ~= 0)
  462.   {   if (o.invent ~= 0)
  463.       {   inventory_stage=2;
  464.           if (RunRoutines(o,invent)~=0)
  465.           {   if (c_style & NEWLINE_BIT ~= 0) new_line;
  466.               rtrue;
  467.           }
  468.       }
  469.       if (o has light && o has worn)
  470.       {    L__M(##ListMiscellany, 8); flag2=1; }
  471.       else
  472.       {   if (o has light) {  L__M(##ListMiscellany, 9, o); flag2=1; }
  473.           if (o has worn)  {  L__M(##ListMiscellany, 10, o); flag2=1; }
  474.       }
  475.       if (o has container)
  476.       {   if (o has openable)
  477.           {   if (flag2==1) print (string) AND__TX;
  478.               else L__M(##ListMiscellany, 11, o);
  479.               if (o has open)
  480.               {   if (child(o)==0) L__M(##ListMiscellany, 13, o);
  481.                   else L__M(##ListMiscellany, 12, o);
  482.               }
  483.               else
  484.               {   if (o has lockable && o has locked)
  485.                       L__M(##ListMiscellany, 15, o);
  486.                   else L__M(##ListMiscellany, 14, o);
  487.               }
  488.               flag2=1;
  489.           }
  490.           else
  491.               if (child(o)==0 && o has transparent)
  492.               {   if (flag2==1) L__M(##ListMiscellany, 16, o);
  493.                   else L__M(##ListMiscellany, 17, o);
  494.               }
  495.       }
  496.       if (flag2==1) print ")";
  497.   }
  498.  
  499.   if (c_style & CONCEAL_BIT == 0)
  500.   {   flag3 = children(o);
  501.       flag2 = child(o);
  502.   }
  503.   else
  504.   {   flag3 = 0;
  505.       objectloop (p in o)
  506.           if (p hasnt concealed && p hasnt scenery) { flag3++; flag2 = p; }
  507.   }
  508.  
  509.   if (c_style & ALWAYS_BIT ~= 0 && flag3>0)
  510.   {   if (c_style & ENGLISH_BIT ~= 0) L__M(##ListMiscellany, 18, o);
  511.       flag=1;
  512.   }
  513.  
  514.   if (c_style & RECURSE_BIT ~= 0 && flag3>0)
  515.   {   if (o has supporter)
  516.       {   if (c_style & ENGLISH_BIT ~= 0)
  517.           {   if (c_style & TERSE_BIT ~= 0)
  518.                    L__M(##ListMiscellany, 19, o);
  519.               else L__M(##ListMiscellany, 20, o);
  520.               if (o has animate) print (string) WHOM__TX;
  521.               else print (string) WHICH__TX;
  522.           }
  523.           flag=1;
  524.       }
  525.       if (o has container && (o has open || o has transparent))
  526.       {   if (c_style & ENGLISH_BIT ~= 0)
  527.           {   if (c_style & TERSE_BIT ~= 0)
  528.                    L__M(##ListMiscellany, 21, o);
  529.               else L__M(##ListMiscellany, 22, o);
  530.               if (o has animate) print (string) WHOM__TX;
  531.               else print (string) WHICH__TX;
  532.           }
  533.           flag=1;
  534.       }
  535.   }
  536.  
  537.   if (flag==1 && c_style & ENGLISH_BIT ~= 0)
  538.   {   if (flag3 > 1 || flag2 has pluralname)
  539.            print (string) ARE2__TX;
  540.       else print (string) IS2__TX;
  541.   }
  542.  
  543.   if (c_style & NEWLINE_BIT ~= 0) new_line;
  544.  
  545.   if (flag==1)
  546.   {   o = child(o);
  547.       @push lt_value; @push listing_together; @push listing_size;
  548.       lt_value = 0; listing_together = 0; listing_size = 0;
  549.       WriteListR(o, depth+1, stack_p);
  550.       @pull listing_size; @pull listing_together; @pull lt_value;
  551.       if (c_style & TERSE_BIT ~= 0) print ")";
  552.   }
  553. ];
  554.  
  555. ! ----------------------------------------------------------------------------
  556. !  Much better menus can be created using the optional library extension
  557. !  "menus.h".  These are provided for compatibility with previous practice:
  558. ! ----------------------------------------------------------------------------
  559.  
  560. [ LowKey_Menu menu_choices EntryR ChoiceR lines main_title i j;
  561.   menu_nesting++;
  562.  .LKRD;
  563.   menu_item=0;
  564.   lines=indirect(EntryR);
  565.   main_title=item_name;
  566.  
  567.   print "--- "; print (string) main_title; print " ---^^";
  568.  
  569.   if (menu_choices ofclass Routine) menu_choices.call();
  570.   else print (string) menu_choices;
  571.  
  572.   for (::)
  573.   {   L__M(##Miscellany, 52, lines);
  574.       print "> ";
  575.  
  576.       #IFV3; read buffer parse;
  577.       #IFNOT; read buffer parse DrawStatusLine;
  578.       #ENDIF;
  579.  
  580.       i=parse-->1;
  581.       if (i==QUIT1__WD or QUIT2__WD || parse->1==0)
  582.       {   menu_nesting--; if (menu_nesting>0) rfalse;
  583.           if (deadflag==0) <<Look>>;
  584.           rfalse;
  585.       }
  586.       i=TryNumber(1);
  587.       if (i==0) jump LKRD;
  588.       if (i<1 || i>lines) continue;
  589.       menu_item=i;
  590.       j=indirect(ChoiceR);
  591.       if (j==2) jump LKRD;
  592.       if (j==3) rfalse;
  593.   }
  594. ];
  595.  
  596. #IFV3;
  597. [ DoMenu menu_choices EntryR ChoiceR;
  598.   LowKey_Menu(menu_choices,EntryR,ChoiceR);
  599. ];
  600. #ENDIF;
  601.  
  602. #IFV5;
  603. [ DoMenu menu_choices EntryR ChoiceR
  604.          lines main_title main_wid cl i j oldcl pkey;
  605.  
  606.   if (pretty_flag==0)
  607.       return LowKey_Menu(menu_choices,EntryR,ChoiceR);
  608.  
  609.   menu_nesting++;
  610.   menu_item=0;
  611.   lines=indirect(EntryR);
  612.   main_title=item_name; main_wid=item_width;
  613.   cl=7;
  614.  
  615.   .ReDisplay;
  616.       oldcl=0;
  617.       @erase_window $ffff;
  618.       i=lines+7;
  619.       @split_window i;
  620.       i = 0->33;
  621.       if (i==0) i=80;
  622.       @set_window 1;
  623.       @set_cursor 1 1;
  624.       style reverse;
  625.       spaces(i); j=i/2-main_wid;
  626.       @set_cursor 1 j;
  627.       print (string) main_title;
  628.       @set_cursor 2 1; spaces(i);
  629.       @set_cursor 2 2; print (string) NKEY__TX;
  630.       j=i-12; @set_cursor 2 j; print (string) PKEY__TX;
  631.       @set_cursor 3 1; spaces(i);
  632.       @set_cursor 3 2; print (string) RKEY__TX;
  633.       j=i-17; @set_cursor 3 j;
  634.       if (menu_nesting==1) print (string) QKEY1__TX;
  635.                       else print (string) QKEY2__TX;
  636.       style roman;
  637.       @set_cursor 5 2; font off;
  638.  
  639.       if (menu_choices ofclass String) print (string) menu_choices;
  640.       else menu_choices.call();
  641.  
  642.       for (::)
  643.       {   if (cl ~= oldcl)
  644.           {   if (oldcl>0) { @set_cursor oldcl 4; print " "; }
  645.               @set_cursor cl 4; print ">";
  646.           }
  647.           oldcl=cl;
  648.           @read_char 1 -> pkey;
  649.           if (pkey==NKEY1__KY or NKEY2__KY or 130)
  650.           {   cl++; if (cl==7+lines) cl=7; continue;
  651.           }
  652.           if (pkey==PKEY1__KY or PKEY2__KY or 129)
  653.           {   cl--; if (cl==6)  cl=6+lines; continue;
  654.           }
  655.           if (pkey==QKEY1__KY or QKEY2__KY or 27 or 131) break;
  656.           if (pkey==10 or 13 or 132)
  657.           {   @set_window 0; font on;
  658.               new_line; new_line; new_line;
  659.     
  660.               menu_item=cl-6;
  661.               EntryR.call();
  662.     
  663.               @erase_window $ffff;
  664.               @split_window 1;
  665.               i = 0->33; if (i==0) { i=80; }
  666.               @set_window 1; @set_cursor 1 1; style reverse; spaces(i);
  667.               j=i/2-item_width;
  668.               @set_cursor 1 j;
  669.               print (string) item_name;
  670.               style roman; @set_window 0; new_line;
  671.     
  672.               i = ChoiceR.call();
  673.               if (i==2) jump ReDisplay;
  674.               if (i==3) break;
  675.     
  676.               L__M(##Miscellany, 53);
  677.               @read_char 1 -> pkey; jump ReDisplay;
  678.           }
  679.       }
  680.  
  681.       menu_nesting--; if (menu_nesting>0) rfalse;
  682.       font on; @set_cursor 1 1;
  683.       @erase_window $ffff; @set_window 0;
  684.       new_line; new_line; new_line;
  685.       if (deadflag==0) <<Look>>;
  686. ];  
  687. #ENDIF;
  688.  
  689. ! ----------------------------------------------------------------------------
  690. !   A cunning routine (which could have been a daemon, but isn't, for the
  691. !   sake of efficiency) to move objects which could be in many rooms about
  692. !   so that the player never catches one not in place
  693. ! ----------------------------------------------------------------------------
  694.  
  695. [ MoveFloatingObjects i k l m address flag;
  696.   objectloop (i)
  697.   {   address=i.&found_in;
  698.       if (address~=0 && i hasnt absent)
  699.       {   if (ZRegion(address-->0)==2)
  700.           {   if (i.found_in() ~= 0) move i to location; else remove i;
  701.           }
  702.           else
  703.           {   k=i.#found_in;
  704.               for (l=0: l<k/2: l++)
  705.               {   m=address-->l;
  706.                   if (m==location || m in location)
  707.                   {   if (i notin location) move i to location;
  708.                       flag = true;
  709.                   }
  710.               }
  711.               if (flag == false) { if (parent(i)) remove i; }
  712.           }
  713.       }
  714.   }
  715. ];
  716.  
  717. ! ----------------------------------------------------------------------------
  718. !   Two little routines for moving the player safely.
  719. ! ----------------------------------------------------------------------------
  720.  
  721. [ PlayerTo newplace flag;
  722.   move player to newplace;
  723.   while (parent(newplace)~=0) newplace=parent(newplace);
  724.   location=newplace;
  725.   real_location=location; MoveFloatingObjects();
  726.   AdjustLight(1);
  727.   if (flag==0) <Look>;
  728.   if (flag==1) { NoteArrival(); ScoreArrival(); }
  729.   if (flag==2) LookSub(1);
  730. ];
  731.  
  732. [ MovePlayer direc; <Go direc>; <Look>; ];
  733.  
  734. ! ----------------------------------------------------------------------------
  735. !   The handy YesOrNo routine, and some "meta" verbs
  736. ! ----------------------------------------------------------------------------
  737.  
  738. [ YesOrNo i;
  739.   for (::)
  740.   {   if (location == nothing || parent(player) == nothing) read buffer parse;
  741.       else read buffer parse DrawStatusLine;
  742.       i=parse-->1;
  743.       if (i==YES1__WD or YES2__WD or YES3__WD) rtrue;
  744.       if (i==NO1__WD or NO2__WD or NO3__WD) rfalse;
  745.       L__M(##Quit,1); print "> ";
  746.   }
  747. ];
  748.  
  749. [ QuitSub; L__M(##Quit,2); if (YesOrNo()~=0) quit; ];
  750.  
  751. [ RestartSub; L__M(##Restart,1);
  752.   if (YesOrNo()~=0) { @restart; L__M(##Restart,2); }
  753. ];
  754.  
  755. [ RestoreSub;
  756.   restore Rmaybe;
  757.   return L__M(##Restore,1);
  758.   .RMaybe; L__M(##Restore,2);
  759. ];
  760.  
  761. [ SaveSub flag;
  762.   #IFV5;
  763.   @save -> flag;
  764.   switch (flag) {
  765.       0: L__M(##Save,1);
  766.       1: L__M(##Save,2);
  767.       2: L__M(##Restore,2);
  768.   }
  769.   #IFNOT;
  770.   save Smaybe;
  771.   return L__M(##Save,1);
  772.   .SMaybe; L__M(##Save,2);
  773.   #ENDIF;
  774. ];
  775.  
  776. [ VerifySub;
  777.   @verify ?Vmaybe;
  778.   jump Vwrong;
  779.   .Vmaybe; return L__M(##Verify,1);
  780.   .Vwrong;
  781.   L__M(##Verify,2);
  782. ];
  783.  
  784. [ ScriptOnSub;
  785.   transcript_mode = ((0-->8) & 1);
  786.   if (transcript_mode) return L__M(##ScriptOn,1);
  787.   @output_stream 2;
  788.   if (((0-->8) & 1) == 0) return L__M(##ScriptOn,3);
  789.   L__M(##ScriptOn,2); VersionSub();
  790.   transcript_mode = true;
  791. ];
  792.     
  793. [ ScriptOffSub;
  794.   transcript_mode = ((0-->8) & 1);
  795.   if (transcript_mode == false) return L__M(##ScriptOff,1);
  796.   L__M(##ScriptOff,2);
  797.   @output_stream -2;
  798.   if ((0-->8) & 1) return L__M(##ScriptOff,3);
  799.   transcript_mode = false;
  800. ];
  801.  
  802. [ NotifyOnSub; notify_mode=1; L__M(##NotifyOn); ];
  803. [ NotifyOffSub; notify_mode=0; L__M(##NotifyOff); ];
  804.  
  805. [ Places1Sub i j k;
  806.   L__M(##Places);
  807.   objectloop(i has visited) j++;
  808.  
  809.   objectloop(i has visited)
  810.   {   print (name) i; k++;
  811.       if (k==j) ".";
  812.       if (k==j-1) print (string) AND__TX; else print ", ";
  813.   }
  814. ];
  815. [ Objects1Sub i j f;
  816.   L__M(##Objects,1);
  817.   objectloop(i has moved)
  818.   {   f=1; print (the) i; j=parent(i);
  819.  
  820.       if (j)
  821.       {   if (j==player)
  822.           {   if (i has worn) L__M(##Objects, 3);
  823.               else L__M(##Objects, 4);
  824.               jump obj__ptd;
  825.           }
  826.  
  827.           if (j has animate)   { L__M(##Objects, 5); jump obj__ptd; }
  828.           if (j has visited)   { L__M(##Objects, 6, j); jump obj__ptd; }
  829.           if (j has container) { L__M(##Objects, 8, j); jump obj__ptd; }
  830.           if (j has supporter) { L__M(##Objects, 9, j); jump obj__ptd; }
  831.           if (j has enterable) { L__M(##Objects, 7, j); jump obj__ptd; }
  832.       }
  833.  
  834.       L__M(##Objects, 10);
  835.       .obj__ptd; new_line;
  836.   }
  837.   if (f==0) L__M(##Objects,2);
  838. ];
  839.  
  840. ! ----------------------------------------------------------------------------
  841. !   The scoring system
  842. ! ----------------------------------------------------------------------------
  843.  
  844. [ ScoreSub;
  845.   L__M(##Score);
  846.   PrintRank();
  847. ];
  848.  
  849. [ Achieved num;
  850.   if (task_done->num==0)
  851.   {   task_done->num=1;
  852.       score = score + task_scores->num;
  853.   }
  854. ];
  855.  
  856. [ PANum m n;
  857.   print "  ";
  858.   n=m;
  859.   if (n<0)    { n=-m; n=n*10; }
  860.   if (n<10)   { print "   "; jump panuml; }
  861.   if (n<100)  { print "  "; jump panuml; }
  862.   if (n<1000) { print " "; }
  863. .panuml;
  864.   print m, " ";
  865. ];
  866.  
  867. [ FullScoreSub i;
  868.   ScoreSub();
  869.   if (score==0 || TASKS_PROVIDED==1) rfalse;
  870.   new_line;
  871.   L__M(##FullScore,1);
  872.  
  873.   for (i=0:i<NUMBER_TASKS:i++)
  874.       if (task_done->i==1)
  875.       {   PANum(task_scores->i);
  876.           PrintTaskName(i);
  877.       }
  878.   
  879.   if (things_score~=0)
  880.   {   PANum(things_score); L__M(##FullScore,2); }
  881.   if (places_score~=0)
  882.   {   PANum(places_score); L__M(##FullScore,3); }
  883.   new_line; PANum(score); L__M(##FullScore,4);
  884. ];
  885.  
  886. ! ----------------------------------------------------------------------------
  887. !   Real verbs start here: Inventory
  888. ! ----------------------------------------------------------------------------
  889.  
  890. [ InvWideSub;
  891.   inventory_style = FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT;
  892.   <Inv>;
  893. ];
  894.  
  895. [ InvTallSub;
  896.   inventory_style = FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + RECURSE_BIT;
  897.   <Inv>;
  898. ];
  899.  
  900. [ InvSub x;
  901.   if (child(player)==0) return L__M(##Inv,1);
  902.   if (inventory_style==0) return InvTallSub();
  903.  
  904.   L__M(##Inv,2);
  905.   if (inventory_style & NEWLINE_BIT ~= 0) print ":^"; else print " ";
  906.  
  907.   WriteListFrom(child(player), inventory_style, 1);
  908.   if (inventory_style & ENGLISH_BIT ~= 0) print ".^";
  909.  
  910. #IFNDEF MANUAL_PRONOUNS;
  911.   objectloop(x in player) PronounNotice(x);
  912. #ENDIF;
  913.   x = 0; ! To prevent a "not used" error
  914.   AfterRoutines();
  915. ];
  916.  
  917. ! ----------------------------------------------------------------------------
  918. !   The object tree and determining the possibility of moves
  919. ! ----------------------------------------------------------------------------
  920.  
  921. [ CommonAncestor o1 o2 i j;
  922.   !  Find the nearest object indirectly containing o1 and o2,
  923.   !  or return 0 if there is no common ancestor.
  924.  
  925.   i = o1;
  926.   while (i ~= 0)
  927.   {
  928.       j = o2;
  929.       while (j ~= 0)
  930.       {   if (j == i) return i;
  931.           j = parent(j);
  932.       }
  933.       i = parent(i);
  934.   }
  935.   return 0;
  936. ];
  937.  
  938. [ IndirectlyContains o1 o2;
  939.   !  Does o1 indirectly contain o2?  (Same as testing if their common
  940.   !  ancestor is o1.)
  941.  
  942.   while (o2~=0)
  943.   {   if (o1==o2) rtrue;
  944.       o2=parent(o2);
  945.   }
  946.   rfalse;
  947. ];
  948.  
  949. [ ObjectScopedBySomething item i j k l m;
  950.   i = item;
  951.   while (parent(i) ~= 0) i=parent(i);
  952.   objectloop (j .& add_to_scope)
  953.   {   l = j.&add_to_scope;
  954.       k = (j.#add_to_scope)/2;
  955.       if (l-->0 ofclass Routine) continue;
  956.       for (m=0:m<k:m++)
  957.           if (l-->m == i)
  958.               return j;
  959.   }
  960.   rfalse;
  961. ];
  962.  
  963. [ ObjectIsUntouchable item flag1 flag2 ancestor i;
  964.  
  965.   ! Determine if there's any barrier preventing the player from moving
  966.   ! things to "item".  Return false if no barrier; otherwise print a
  967.   ! suitable message and return true.
  968.   ! If flag1 is set, do not print any message.
  969.   ! If flag2 is set, also apply Take/Remove restrictions.
  970.  
  971.   ! If the item has been added to scope by something, it's first necessary
  972.   ! for that something to be touchable.
  973.  
  974.   i = ObjectScopedBySomething(item);
  975.   if (i ~= 0)
  976.   {   if (ObjectIsUntouchable(i)) return;
  977.       ! An item immediately added to scope
  978.   }
  979.  
  980.   ancestor = CommonAncestor(player, item);
  981.  
  982.   ! First, a barrier between the player and the ancestor.  The player
  983.   ! can only be in a sequence of enterable objects, and only closed
  984.   ! containers form a barrier.
  985.  
  986.   if (player ~= ancestor)
  987.   {   i = parent(player);
  988.       while (i~=ancestor)
  989.       {   if (i has container && i hasnt open)
  990.           {   if (flag1) rtrue;
  991.               return L__M(##Take,9,i);
  992.           }
  993.           i = parent(i);
  994.       }
  995.   }
  996.  
  997.   ! Second, a barrier between the item and the ancestor.  The item can
  998.   ! be carried by someone, part of a piece of machinery, in or on top
  999.   ! of something and so on.
  1000.  
  1001.   if (item ~= ancestor)
  1002.   {   i = parent(item);
  1003.       while (i~=ancestor)
  1004.       {   if (flag2 && i hasnt container && i hasnt supporter)
  1005.           {   if (i has animate)
  1006.               {   if (flag1) rtrue;
  1007.                   return L__M(##Take,6,i);
  1008.               }
  1009.               if (i has transparent)
  1010.               {   if (flag1) rtrue;
  1011.                   return L__M(##Take,7,i);
  1012.               }
  1013.               if (flag1) rtrue;
  1014.               return L__M(##Take,8,item);
  1015.           }
  1016.           if (i has container && i hasnt open)
  1017.           {   if (flag1) rtrue;
  1018.               return L__M(##Take,9,i);
  1019.           }
  1020.           i = parent(i);
  1021.       }
  1022.   }
  1023.   rfalse;
  1024. ];
  1025.  
  1026. [ AttemptToTakeObject item     ancestor after_recipient i j k;
  1027.   ! Try to transfer the given item to the player: return false
  1028.   ! if successful, true if unsuccessful, printing a suitable message
  1029.   ! in the latter case.
  1030.  
  1031.   ! People cannot ordinarily be taken.
  1032.   if (item == player) return L__M(##Take,2);
  1033.   if (item has animate) return L__M(##Take,3,item);
  1034.  
  1035.   ancestor = CommonAncestor(player, item);
  1036.  
  1037.   if (ancestor == 0)
  1038.   {   i = ObjectScopedBySomething(item);
  1039.       if (i ~= 0) ancestor = CommonAncestor(player, i);
  1040.   }
  1041.  
  1042.   ! Are player and item in totally different places?
  1043.  
  1044.   if (ancestor == 0) return L__M(##Take,8,item);
  1045.  
  1046.   ! Is the player indirectly inside the item?
  1047.   if (ancestor == item) return L__M(##Take,4,item);
  1048.  
  1049.   ! Does the player already directly contain the item?
  1050.   if (item in player) return L__M(##Take,5,item);
  1051.  
  1052.   ! Can the player touch the item, or is there (e.g.) a closed container
  1053.   ! in the way?
  1054.   if (ObjectIsUntouchable(item,false,true)) return;
  1055.  
  1056.   ! The item is now known to be accessible.
  1057.  
  1058.   ! Consult the immediate possessor of the item, if it's in a container
  1059.   ! which the player is not in.
  1060.  
  1061.   i=parent(item);
  1062.   if (i ~= ancestor && (i has container || i has supporter))
  1063.   {   after_recipient=i;
  1064.       k=action; action=##LetGo;
  1065.       if (RunRoutines(i,before)~=0) { action=k; rtrue; }
  1066.       action=k;
  1067.   }
  1068.  
  1069.   if (item has scenery) return L__M(##Take,10,item);
  1070.   if (item has static)  return L__M(##Take,11,item);
  1071.  
  1072.   ! The item is now known to be available for taking.  Is the player
  1073.   ! carrying too much?  If so, possibly juggle items into the rucksack
  1074.   ! to make room.
  1075.  
  1076.   k=0; objectloop (j in player) if (j hasnt worn) k++;
  1077.  
  1078.   if (k >= ValueOrRun(player,capacity))
  1079.   {   if (SACK_OBJECT~=0)
  1080.       {   if (parent(SACK_OBJECT)~=player)
  1081.               return L__M(##Take,12);
  1082.           j=0;
  1083.           objectloop (k in player) 
  1084.               if (k~=SACK_OBJECT && k hasnt worn && k hasnt light) j=k;
  1085.  
  1086.           if (j~=0)
  1087.           {   L__M(##Take,13,j);
  1088.               keep_silent = 1; <Insert j SACK_OBJECT>; keep_silent = 0;
  1089.               if (j notin SACK_OBJECT) rtrue;
  1090.           }
  1091.           else return L__M(##Take,12);
  1092.       }
  1093.       else return L__M(##Take,12);
  1094.   }
  1095.  
  1096.   ! Transfer the item.
  1097.  
  1098.   move item to player;
  1099.  
  1100.   ! Send "after" message to the object letting go of the item, if any.
  1101.  
  1102.   if (after_recipient~=0)
  1103.   {   k=action; action=##LetGo;
  1104.       if (RunRoutines(after_recipient,after)~=0) { action=k; rtrue; }
  1105.       action=k;
  1106.   }
  1107.   rfalse;
  1108. ];
  1109.  
  1110. ! ----------------------------------------------------------------------------
  1111. !   Object movement verbs
  1112. ! ----------------------------------------------------------------------------
  1113.  
  1114. [ TakeSub;
  1115.   if (onotheld_mode==0 || noun notin player)
  1116.       if (AttemptToTakeObject(noun)) rtrue;
  1117.   if (AfterRoutines()==1) rtrue;
  1118.   notheld_mode=onotheld_mode;
  1119.   if (notheld_mode==1 || keep_silent==1) rtrue;
  1120.   L__M(##Take,1);
  1121. ];
  1122.  
  1123. [ RemoveSub i;
  1124.   i=parent(noun);
  1125.   if (i has container && i hasnt open) return L__M(##Remove,1,noun);
  1126.   if (i~=second) return L__M(##Remove,2,noun);
  1127.   if (i has animate) return L__M(##Take,6,i);
  1128.   if (AttemptToTakeObject(noun)) rtrue;
  1129.   action=##Remove; if (AfterRoutines()==1) rtrue;
  1130.   action=##Take;   if (AfterRoutines()==1) rtrue;
  1131.  
  1132.   if (keep_silent==1) rtrue;
  1133.   return L__M(##Remove,3,noun);
  1134. ];
  1135.  
  1136. [ DropSub;
  1137.   if (noun == player) return L__M(##PutOn, 4);
  1138.   if (noun in parent(player)) return L__M(##Drop,1,noun);
  1139.   if (noun notin player) return L__M(##Drop,2,noun);
  1140.   if (noun has worn)
  1141.   {   L__M(##Drop,3,noun);
  1142.       <Disrobe noun>;
  1143.       if (noun has worn && noun in player) rtrue;
  1144.   }
  1145.   move noun to parent(player);
  1146.   if (AfterRoutines()==1) rtrue;
  1147.   if (keep_silent==1) rtrue;
  1148.   return L__M(##Drop,4,noun);
  1149. ];
  1150.  
  1151. [ PutOnSub ancestor;
  1152.   receive_action=##PutOn; 
  1153.   if (second == d_obj || player in second) <<Drop noun>>;
  1154.   if (parent(noun)~=player) return L__M(##PutOn,1,noun);
  1155.  
  1156.   ancestor = CommonAncestor(noun, second);
  1157.   if (ancestor == noun) return L__M(##PutOn,2,noun);
  1158.   if (ObjectIsUntouchable(second)) return;
  1159.  
  1160.   if (second ~= ancestor)
  1161.   {   action=##Receive;
  1162.       if (RunRoutines(second,before)~=0) { action=##PutOn; return; }
  1163.       action=##PutOn;
  1164.   }
  1165.   if (second hasnt supporter) return L__M(##PutOn,3,second);
  1166.   if (ancestor == player) return L__M(##PutOn,4);
  1167.   if (noun has worn)
  1168.   {   L__M(##PutOn,5,noun); <Disrobe noun>; if (noun has worn) return;
  1169.   }
  1170.  
  1171.   if (children(second)>=ValueOrRun(second,capacity))
  1172.       return L__M(##PutOn,6,second);
  1173.  
  1174.   move noun to second;
  1175.  
  1176.   if (AfterRoutines()==1) return;
  1177.  
  1178.   if (second ~= ancestor)
  1179.   {   action=##Receive;
  1180.       if (RunRoutines(second,after)~=0) { action=##PutOn; return; }
  1181.       action=##PutOn;
  1182.   }
  1183.   if (keep_silent==1) return;
  1184.   if (multiflag==1) return L__M(##PutOn,7);
  1185.   L__M(##PutOn,8,noun);
  1186. ];
  1187.  
  1188. [ InsertSub ancestor;
  1189.   receive_action = ##Insert;
  1190.   if (second==d_obj || player in second) <<Drop noun>>;
  1191.   if (parent(noun)~=player) return L__M(##Insert,1,noun);
  1192.  
  1193.   ancestor = CommonAncestor(noun, second);
  1194.   if (ancestor == noun) return L__M(##Insert, 5, noun);
  1195.   if (ObjectIsUntouchable(second)) return;
  1196.  
  1197.   if (second ~= ancestor)
  1198.   {   action=##Receive;
  1199.       if (RunRoutines(second,before)~=0) { action=##Insert; rtrue; }
  1200.       action=##Insert;
  1201.       if (second has container && second hasnt open)
  1202.           return L__M(##Insert,3,second);
  1203.   }
  1204.   if (second hasnt container) return L__M(##Insert,2,second);
  1205.  
  1206.   if (noun has worn)
  1207.   {   L__M(##Insert,6,noun); <Disrobe noun>; if (noun has worn) return;
  1208.   }
  1209.  
  1210.   if (children(second) >= ValueOrRun(second,capacity))
  1211.       return L__M(##Insert,7,second);
  1212.  
  1213.   move noun to second;
  1214.  
  1215.   if (AfterRoutines()==1) rtrue;
  1216.  
  1217.   if (second ~= ancestor)
  1218.   {   action=##Receive;
  1219.       if (RunRoutines(second,after)~=0) { action=##Insert; rtrue; }
  1220.       action=##Insert;
  1221.   }
  1222.   if (keep_silent==1) rtrue;
  1223.   if (multiflag==1) return L__M(##Insert,8,noun);
  1224.   L__M(##Insert,9,noun);
  1225. ];
  1226.  
  1227. ! ----------------------------------------------------------------------------
  1228. !   Empties and transfers are routed through the actions above
  1229. ! ----------------------------------------------------------------------------
  1230.  
  1231. [ TransferSub;
  1232.   if (noun notin player && AttemptToTakeObject(noun)) return;
  1233.   if (second has supporter) <<PutOn noun second>>;
  1234.   if (second == d_obj) <<Drop noun>>;
  1235.   <<Insert noun second>>;
  1236. ];
  1237.  
  1238. [ EmptySub;
  1239.   second=d_obj; EmptyTSub();
  1240. ];
  1241.  
  1242. [ EmptyTSub i j k flag;
  1243.   if (noun == second) return L__M(##EmptyT,4);
  1244.   if (ObjectIsUntouchable(noun)) return;
  1245.   if (noun hasnt container) return L__M(##EmptyT,1,noun);
  1246.   if (noun hasnt open) return L__M(##EmptyT,2,noun);
  1247.   if (second~=d_obj)
  1248.   {   if (second hasnt supporter)
  1249.       {   if (second hasnt container) return L__M(##EmptyT,1,second);
  1250.           if (second hasnt open) return L__M(##EmptyT,2,second);
  1251.       }
  1252.   }
  1253.   i=child(noun); k = children(noun);
  1254.   if (i==0) return L__M(##EmptyT,3,noun);
  1255.   while (i~=0)
  1256.   {   j=sibling(i);
  1257.       flag = 0;
  1258.       if (ObjectIsUntouchable(noun)) flag = 1;
  1259.       if (noun hasnt container) flag = 1;
  1260.       if (noun hasnt open) flag = 1;
  1261.       if (second~=d_obj)
  1262.       {   if (second hasnt supporter)
  1263.           {   if (second hasnt container) flag = 1;
  1264.               if (second hasnt open) flag = 1;
  1265.           }
  1266.       }
  1267.       if (k-- == 0) flag = 1;
  1268.       if (flag) break;
  1269.       if (keep_silent == 0) print (name) i, ": ";
  1270.       <Transfer i second>;
  1271.       i=j;
  1272.   }
  1273. ];
  1274.  
  1275. ! ----------------------------------------------------------------------------
  1276. !   Gifts
  1277. ! ----------------------------------------------------------------------------
  1278.  
  1279. [ GiveSub;
  1280.   if (parent(noun)~=player) return L__M(##Give,1,noun);
  1281.   if (second==player)  return L__M(##Give,2,noun);
  1282.   if (RunLife(second,##Give)~=0) rfalse;
  1283.   L__M(##Give,3,second);
  1284. ];
  1285.  
  1286. [ GiveRSub; <Give second noun>; ];
  1287.  
  1288. [ ShowSub;
  1289.   if (parent(noun)~=player) return L__M(##Show,1,noun);
  1290.   if (second==player) <<Examine noun>>;
  1291.   if (RunLife(second,##Show)~=0) rfalse;
  1292.   L__M(##Show,2,second);
  1293. ];
  1294.  
  1295. [ ShowRSub; <Show second noun>; ];
  1296.  
  1297. ! ----------------------------------------------------------------------------
  1298. !   Travelling around verbs
  1299. ! ----------------------------------------------------------------------------
  1300.  
  1301. [ EnterSub ancestor j k;
  1302.   if (noun has door || noun in compass) <<Go noun>>;
  1303.  
  1304.   if (player in noun) return L__M(##Enter,1,noun);
  1305.   if (noun hasnt enterable) return L__M(##Enter,2,noun);
  1306.   if (noun has container && noun hasnt open) return L__M(##Enter,3,noun);
  1307.  
  1308.   if (parent(player) ~= parent(noun))
  1309.   {   ancestor = CommonAncestor(player, noun);
  1310.       if (ancestor == player or 0) return L__M(##Enter,4,noun);
  1311.       while (player notin ancestor)
  1312.       {   j = parent(player);
  1313.           k = keep_silent; 
  1314.           if (parent(j) ~= ancestor || noun ~= ancestor)
  1315.           {   L__M(##Enter,6,j);
  1316.               keep_silent = 1;
  1317.           }
  1318.           <Exit>;
  1319.           keep_silent = k;
  1320.           if (player in j) return;
  1321.       }
  1322.       if (player in noun) return;
  1323.       if (noun notin ancestor)
  1324.       {   j = parent(noun);
  1325.           while (parent(j) ~= ancestor) j = parent(j);
  1326.           L__M(##Enter,7,j);
  1327.           k = keep_silent; keep_silent = 1;
  1328.           <Enter j>;
  1329.           keep_silent = k;
  1330.           if (player notin j) return;
  1331.           <<Enter noun>>;
  1332.       }
  1333.   }
  1334.  
  1335.   move player to noun;
  1336.   if (AfterRoutines()==1) rtrue;
  1337.   if (keep_silent==1) rtrue;
  1338.   L__M(##Enter,5,noun);
  1339.   Locale(noun);
  1340. ];
  1341.  
  1342. [ GetOffSub;
  1343.   if (parent(player)==noun) <<Exit>>;
  1344.   L__M(##GetOff,1,noun);
  1345. ];
  1346.  
  1347. [ ExitSub p;
  1348.   p=parent(player);
  1349.   if (p==location || (location==thedark && p==real_location))
  1350.   {   if ((location.out_to~=0)
  1351.           || (location==thedark && real_location.out_to~=0)) <<Go out_obj>>;
  1352.       return L__M(##Exit,1);
  1353.   }
  1354.   if (p has container && p hasnt open)
  1355.       return L__M(##Exit,2,p);
  1356.  
  1357.   move player to parent(p);
  1358.  
  1359.   if (AfterRoutines()==1) rtrue;
  1360.   if (keep_silent==1) rtrue;
  1361.   L__M(##Exit,3,p); LookSub(1);
  1362. ];
  1363.  
  1364. [ VagueGoSub; L__M(##VagueGo); ];
  1365.  
  1366. [ GoInSub;
  1367.   <<Go in_obj>>;
  1368. ];
  1369.  
  1370. [ GoSub i j k df movewith thedir old_loc;
  1371.  
  1372.   if (second ~= 0 && second notin Compass
  1373.       && ObjectIsUntouchable(second)) return;
  1374.  
  1375.   old_loc = location;
  1376.   movewith=0;
  1377.   i=parent(player);
  1378.   if ((location~=thedark && i~=location)
  1379.       || (location==thedark && i~=real_location))
  1380.   {   j=location;
  1381.       if (location==thedark) location=real_location;
  1382.       k=RunRoutines(i,before); if (k~=3) location=j;
  1383.       if (k==1)
  1384.       {   movewith=i; i=parent(i);
  1385.       }
  1386.       else
  1387.       {   if (k==0) L__M(##Go,1,i);
  1388.           rtrue;
  1389.       }
  1390.   }
  1391.  
  1392.   thedir=noun.door_dir;
  1393.   if (ZRegion(thedir)==2) thedir=RunRoutines(noun,door_dir);
  1394.   
  1395.   j=i.thedir; k=ZRegion(j);
  1396.   if (k==3) { print (string) j; new_line; rfalse; }
  1397.   if (k==2) { j=RunRoutines(i,thedir);
  1398.               if (j==1) rtrue;
  1399.             }
  1400.  
  1401.   if (k==0 || j==0)
  1402.   {   if (i.cant_go ~= 0) PrintOrRun(i, cant_go);
  1403.       rfalse;
  1404.   }
  1405.  
  1406.   if (j has door)
  1407.   {   if (j has concealed) return L__M(##Go,2);
  1408.       if (j hasnt open)
  1409.       {   if (noun==u_obj) return L__M(##Go,3,j);
  1410.           if (noun==d_obj) return L__M(##Go,4,j);
  1411.           return L__M(##Go,5,j);
  1412.       }
  1413.       k=RunRoutines(j,door_to);
  1414.       if (k==0) return L__M(##Go,6,j);
  1415.       if (k==1) rtrue;
  1416.       j = k;
  1417.   }
  1418.   if (movewith==0) move player to j; else move movewith to j;
  1419.  
  1420.   location=j; MoveFloatingObjects();
  1421.   df=OffersLight(j);
  1422.   if (df~=0) { location=j; real_location=j; lightflag=1; }
  1423.   else
  1424.   {   if (old_loc == thedark)
  1425.       {   DarkToDark();
  1426.           if (deadflag~=0) rtrue;
  1427.       }
  1428.       real_location=j;
  1429.       location=thedark; lightflag=0;
  1430.   }
  1431.   if (AfterRoutines()==1) rtrue;
  1432.   if (keep_silent==1) rtrue;
  1433.   LookSub(1);
  1434. ];
  1435.  
  1436. ! ----------------------------------------------------------------------------
  1437. !   Describing the world.  SayWhatsOn(object) does just that (producing
  1438. !   no text if nothing except possibly "scenery" and "concealed" items are).
  1439. !   Locale(object) runs through the "tail end" of a Look-style room
  1440. !   description for the contents of the object, printing up suitable
  1441. !   descriptions as it goes.
  1442. ! ----------------------------------------------------------------------------
  1443.  
  1444. [ SayWhatsOn descon j f;
  1445.   if (descon==parent(player)) rfalse;
  1446.   objectloop (j in descon)
  1447.       if (j hasnt concealed && j hasnt scenery) f=1;
  1448.   if (f==0) rfalse;
  1449.   L__M(##Look, 4, descon); rtrue;
  1450. ];
  1451.  
  1452. [ NotSupportingThePlayer o i;
  1453.   i=parent(player);
  1454.   while (i~=0 && i~=visibility_ceiling)
  1455.   {   if (i==o) rfalse;
  1456.       i = parent(i);
  1457.       if (i~=0 && i hasnt supporter) rtrue;
  1458.   }
  1459.   rtrue;
  1460. ];
  1461.  
  1462. [ Locale descin text1 text2 o k p j f2 flag;
  1463.  
  1464.   objectloop (o in descin) give o ~workflag;
  1465.  
  1466.   k=0;
  1467.   objectloop (o in descin)
  1468.       if (o hasnt concealed && NotSupportingThePlayer(o))
  1469.       {  #IFNDEF MANUAL_PRONOUNS;
  1470.          PronounNotice(o);
  1471.          #ENDIF;
  1472.          if (o hasnt scenery)
  1473.          {   give o workflag; k++;
  1474.              p=initial; f2=0;
  1475.              if ((o has door || o has container)
  1476.                  && o has open && o provides when_open)
  1477.              {   p = when_open; f2 = 1; jump Prop_Chosen; }
  1478.              if ((o has door || o has container)
  1479.                  && o hasnt open && o provides when_closed)
  1480.              {   p = when_closed; f2 = 1; jump Prop_Chosen; }
  1481.              if (o has switchable
  1482.                  && o has on && o provides when_on)
  1483.              {   p = when_on; f2 = 1; jump Prop_Chosen; }
  1484.              if (o has switchable
  1485.                  && o hasnt on && o provides when_off)
  1486.              {   p = when_off; f2 = 1; }
  1487.  
  1488.              .Prop_Chosen;
  1489.  
  1490.              if (o hasnt moved || o.describe~=NULL || f2==1)
  1491.              {   if (o.describe~=NULL && RunRoutines(o,describe)~=0)
  1492.                  {   flag=1;
  1493.                      give o ~workflag; k--;
  1494.                  }    
  1495.                  else
  1496.                  {   j=o.p;
  1497.                      if (j~=0)
  1498.                      {   new_line;
  1499.                          PrintOrRun(o,p);
  1500.                          flag=1;
  1501.                          give o ~workflag; k--;
  1502.                          if (o has supporter && child(o)~=0) SayWhatsOn(o);
  1503.                      }
  1504.                  }
  1505.              }
  1506.          }
  1507.          else
  1508.              if (o has supporter && child(o)~=0) SayWhatsOn(o);
  1509.       }
  1510.  
  1511.   if (k==0) return 0;
  1512.  
  1513.   if (text1~=0)
  1514.   {   new_line;
  1515.       if (flag==1) text1=text2;
  1516.       print (string) text1, " ";
  1517.       WriteListFrom(child(descin),
  1518.           ENGLISH_BIT + WORKFLAG_BIT + RECURSE_BIT
  1519.           + PARTINV_BIT + TERSE_BIT + CONCEAL_BIT);
  1520.       return k;
  1521.   }
  1522.            
  1523.   if (flag==1) L__M(##Look,5,descin); else L__M(##Look,6,descin);
  1524. ];
  1525.  
  1526. ! ----------------------------------------------------------------------------
  1527. !   Looking.  LookSub(1) is allowed to abbreviate long descriptions, but
  1528. !     LookSub(0) (which is what happens when the Look action is generated)
  1529. !     isn't.  (Except that these are over-ridden by the player-set lookmode.)
  1530. ! ----------------------------------------------------------------------------
  1531.  
  1532. [ LMode1Sub; lookmode=1; print (string) Story; L__M(##LMode1); ];  ! Brief
  1533.  
  1534. [ LMode2Sub; lookmode=2; print (string) Story; L__M(##LMode2); ];  ! Verbose
  1535.  
  1536. [ LMode3Sub; lookmode=3; print (string) Story; L__M(##LMode3); ];  ! Superbrief
  1537.  
  1538. [ NoteArrival descin;
  1539.   if (location==thedark) { lastdesc = thedark; return; }
  1540.   if (location~=lastdesc)
  1541.   {   if (location.initial~=0) PrintOrRun(location, initial);
  1542.       descin = location;
  1543.       NewRoom();
  1544.       lastdesc = descin;
  1545.   }
  1546. ];
  1547.  
  1548. [ ScoreArrival;
  1549.   if (location hasnt visited)
  1550.   {   give location visited;
  1551.       if (location has scored)
  1552.       {   score = score + ROOM_SCORE;
  1553.           places_score = places_score + ROOM_SCORE;
  1554.       }
  1555.   }
  1556. ];
  1557.  
  1558. [ FindVisibilityLevels visibility_levels;
  1559.   visibility_levels = 1;
  1560.   visibility_ceiling = parent(player);
  1561.   while ((parent(visibility_ceiling) ~= 0)
  1562.          && (visibility_ceiling hasnt container
  1563.              || visibility_ceiling has open
  1564.              || visibility_ceiling has transparent))
  1565.   {   visibility_ceiling = parent(visibility_ceiling);
  1566.       visibility_levels++;
  1567.   }      
  1568.   return visibility_levels;
  1569. ];
  1570.  
  1571. [ LookSub allow_abbrev  visibility_levels i j k;
  1572.   if (parent(player)==0) return RunTimeError(10);
  1573.  
  1574.   .MovedByInitial;
  1575.   if (location == thedark) { visibility_ceiling = thedark; NoteArrival(); }
  1576.   else
  1577.   {   visibility_levels = FindVisibilityLevels();
  1578.       if (visibility_ceiling == location)
  1579.       {   NoteArrival();
  1580.           if (visibility_ceiling ~= location) jump MovedByInitial;
  1581.       }
  1582.   }
  1583.  
  1584.   !   Printing the top line: e.g.
  1585.   !   Octagonal Room (on the table) (as Frodo)
  1586.  
  1587.   new_line;
  1588.   style bold;
  1589.   if (visibility_levels == 0) print (name) thedark;
  1590.   else
  1591.   {   if (visibility_ceiling ~= location) print (The) visibility_ceiling;
  1592.       else print (name) visibility_ceiling;
  1593.   }
  1594.   style roman;
  1595.  
  1596.   for (j=1, i=parent(player):j<visibility_levels:j++, i=parent(i))
  1597.       if (i has supporter) L__M(##Look,1,i);
  1598.                       else L__M(##Look,2,i);
  1599.  
  1600.   if (print_player_flag==1) L__M(##Look,3,player);
  1601.   new_line;
  1602.  
  1603.   !   The room description (if visible)
  1604.  
  1605.   if (lookmode<3 && visibility_ceiling==location)
  1606.   {   if ((allow_abbrev~=1) || (lookmode==2) || (location hasnt visited))
  1607.       {   if (location.describe~=NULL) RunRoutines(location,describe);
  1608.           else
  1609.           {   if (location.description==0) RunTimeError(11,location);
  1610.               else PrintOrRun(location,description);
  1611.           }
  1612.       }
  1613.   }
  1614.  
  1615.   if (visibility_levels == 0) Locale(thedark);
  1616.   else
  1617.   {   for (i=player, j=visibility_levels: j>0: j--, i=parent(i))
  1618.           give i workflag;
  1619.       
  1620.       for (j=visibility_levels: j>0: j--)
  1621.       {   for (i=player, k=0: k<j: k++) i=parent(i);
  1622.           if (i.inside_description~=0)
  1623.           {   new_line; PrintOrRun(i,inside_description); }
  1624.           Locale(i);
  1625.       }
  1626.   }
  1627.  
  1628.   LookRoutine();
  1629.   ScoreArrival();
  1630.  
  1631.   action=##Look;
  1632.   if (AfterRoutines()==1) rtrue;
  1633. ];
  1634.  
  1635. [ ExamineSub i;
  1636.   if (location==thedark) return L__M(##Examine,1);
  1637.   i=noun.description;
  1638.   if (i==0)
  1639.   {   if (noun has container) <<Search noun>>;
  1640.       if (noun has switchable) { L__M(##Examine,3,noun); rfalse; }
  1641.       return L__M(##Examine,2,noun);
  1642.   }
  1643.   PrintOrRun(noun, description);
  1644.   if (noun has switchable) L__M(##Examine,3,noun);
  1645.   if (AfterRoutines()==1) rtrue;
  1646. ];
  1647.  
  1648. [ LookUnderSub;
  1649.   if (location==thedark) return L__M(##LookUnder,1);
  1650.   L__M(##LookUnder,2);
  1651. ];
  1652.  
  1653. [ SearchSub i f;
  1654.   if (location==thedark) return L__M(##Search,1,noun);
  1655.   if (ObjectIsUntouchable(noun)) return;
  1656.   objectloop (i in noun) if (i hasnt concealed && i hasnt scenery) f=1;
  1657.   if (noun has supporter)
  1658.   {   if (f==0) return L__M(##Search,2,noun);
  1659.       return L__M(##Search,3,noun);
  1660.   }
  1661.   if (noun hasnt container) return L__M(##Search,4,noun);
  1662.   if (noun hasnt transparent && noun hasnt open)
  1663.       return L__M(##Search,5,noun);
  1664.   if (AfterRoutines()==1) rtrue;
  1665.  
  1666.   i=children(noun);
  1667.   if (f==0) return L__M(##Search,6,noun);
  1668.   L__M(##Search,7,noun);
  1669. ];
  1670.  
  1671. ! ----------------------------------------------------------------------------
  1672. !   Verbs which change the state of objects without moving them
  1673. ! ----------------------------------------------------------------------------
  1674.  
  1675. [ UnlockSub;
  1676.   if (ObjectIsUntouchable(noun)) return;
  1677.   if (noun hasnt lockable) return L__M(##Unlock,1,noun);
  1678.   if (noun hasnt locked)   return L__M(##Unlock,2,noun);
  1679.   if (noun.with_key~=second) return L__M(##Unlock,3,second);
  1680.   give noun ~locked;
  1681.   if (AfterRoutines()==1) rtrue;
  1682.   if (keep_silent==1) rtrue;
  1683.   L__M(##Unlock,4,noun);
  1684. ];
  1685.  
  1686. [ LockSub;
  1687.   if (ObjectIsUntouchable(noun)) return;
  1688.   if (noun hasnt lockable) return L__M(##Lock,1,noun);
  1689.   if (noun has locked)     return L__M(##Lock,2,noun);
  1690.   if (noun has open)       return L__M(##Lock,3,noun);
  1691.   if (noun.with_key~=second) return L__M(##Lock,4,second);
  1692.   give noun locked;
  1693.   if (AfterRoutines()==1) rtrue;
  1694.   if (keep_silent==1) rtrue;
  1695.   L__M(##Lock,5,noun);
  1696. ];
  1697.  
  1698. [ SwitchonSub;
  1699.   if (ObjectIsUntouchable(noun)) return;
  1700.   if (noun hasnt switchable) return L__M(##SwitchOn,1,noun);
  1701.   if (noun has on) return L__M(##SwitchOn,2,noun);
  1702.   give noun on;
  1703.   if (AfterRoutines()==1) rtrue;
  1704.   if (keep_silent==1) rtrue;
  1705.   L__M(##SwitchOn,3,noun);
  1706. ];
  1707.  
  1708. [ SwitchoffSub;
  1709.   if (ObjectIsUntouchable(noun)) return;
  1710.   if (noun hasnt switchable) return L__M(##SwitchOff,1,noun);
  1711.   if (noun hasnt on) return L__M(##SwitchOff,2,noun);
  1712.   give noun ~on;
  1713.   if (AfterRoutines()==1) rtrue;
  1714.   if (keep_silent==1) rtrue;
  1715.   L__M(##SwitchOff,3,noun);
  1716. ];
  1717.  
  1718. [ OpenSub;
  1719.   if (ObjectIsUntouchable(noun)) return;
  1720.   if (noun hasnt openable) return L__M(##Open,1,noun);
  1721.   if (noun has locked)     return L__M(##Open,2,noun);
  1722.   if (noun has open)       return L__M(##Open,3,noun);
  1723.   give noun open;
  1724.   if (AfterRoutines()==1) rtrue;
  1725.   if (keep_silent==1) rtrue;
  1726.   if (noun has container && noun hasnt transparent && child(noun)~=0
  1727.       && IndirectlyContains(noun,player)==0)
  1728.       return L__M(##Open,4,noun);
  1729.   L__M(##Open,5,noun);
  1730. ];
  1731.  
  1732. [ CloseSub;
  1733.   if (ObjectIsUntouchable(noun)) return;
  1734.   if (noun hasnt openable) return L__M(##Close,1,noun);
  1735.   if (noun hasnt open)     return L__M(##Close,2,noun);
  1736.   give noun ~open;
  1737.   if (AfterRoutines()==1) rtrue;
  1738.   if (keep_silent==1) rtrue;
  1739.   L__M(##Close,3,noun);
  1740. ];
  1741.  
  1742. [ DisrobeSub;
  1743.   if (ObjectIsUntouchable(noun)) return;
  1744.   if (noun hasnt worn) return L__M(##Disrobe,1,noun);
  1745.   give noun ~worn;
  1746.   if (AfterRoutines()==1) rtrue;
  1747.   if (keep_silent==1) rtrue;
  1748.   L__M(##Disrobe,2,noun);
  1749. ];
  1750.  
  1751. [ WearSub;
  1752.   if (ObjectIsUntouchable(noun)) return;
  1753.   if (noun hasnt clothing)  return L__M(##Wear,1,noun);
  1754.   if (parent(noun)~=player) return L__M(##Wear,2,noun);
  1755.   if (noun has worn)        return L__M(##Wear,3,noun);
  1756.   give noun worn;
  1757.   if (AfterRoutines()==1) rtrue;
  1758.   if (keep_silent==1) rtrue;
  1759.   L__M(##Wear,4,noun);
  1760. ];
  1761.  
  1762. [ EatSub;
  1763.   if (ObjectIsUntouchable(noun)) return;
  1764.   if (noun hasnt edible) return L__M(##Eat,1,noun);
  1765.   if (noun has worn)
  1766.   {   L__M(##Drop,3,noun);
  1767.       <Disrobe noun>;
  1768.       if (noun has worn && noun in player) rtrue;
  1769.   }
  1770.   remove noun;
  1771.   if (AfterRoutines()==1) rtrue;
  1772.   if (keep_silent==1) rtrue;
  1773.   L__M(##Eat,2,noun);
  1774. ];
  1775.  
  1776. ! ----------------------------------------------------------------------------
  1777. !   Verbs which are really just stubs (anything which happens for these
  1778. !   actions must happen in before rules)
  1779. ! ----------------------------------------------------------------------------
  1780.  
  1781. [ YesSub; L__M(##Yes); ];
  1782. [ NoSub; L__M(##No); ];
  1783. [ BurnSub; L__M(##Burn,1,noun); ];
  1784. [ PraySub; L__M(##Pray,1,noun); ];
  1785. [ WakeSub; L__M(##Wake,1,noun); ];
  1786. [ WakeOtherSub;
  1787.   if (ObjectIsUntouchable(noun)) return;
  1788.   if (RunLife(noun,##WakeOther)~=0) rfalse;
  1789.   L__M(##WakeOther,1,noun);
  1790. ];
  1791. [ ThinkSub; L__M(##Think,1,noun); ];
  1792. [ SmellSub; L__M(##Smell,1,noun); ];
  1793. [ ListenSub; L__M(##Listen,1,noun); ];
  1794. [ TasteSub; L__M(##Taste,1,noun); ];
  1795. [ DigSub; L__M(##Dig,1,noun); ];
  1796. [ CutSub; L__M(##Cut,1,noun); ];
  1797. [ JumpSub; L__M(##Jump,1,noun); ];
  1798. [ JumpOverSub; L__M(##JumpOver,1,noun); ];
  1799. [ TieSub; L__M(##Tie,1,noun); ];
  1800. [ DrinkSub; L__M(##Drink,1,noun); ];
  1801. [ FillSub; L__M(##Fill,1,noun); ];
  1802. [ SorrySub; L__M(##Sorry,1,noun); ];
  1803. [ StrongSub; L__M(##Strong,1,noun); ];
  1804. [ MildSub; L__M(##Mild,1,noun); ];
  1805. [ SwimSub; L__M(##Swim,1,noun); ];
  1806. [ SwingSub; L__M(##Swing,1,noun); ];
  1807. [ BlowSub; L__M(##Blow,1,noun); ];
  1808. [ RubSub; L__M(##Rub,1,noun); ];
  1809. [ SetSub; L__M(##Set,1,noun); ];
  1810. [ SetToSub; L__M(##SetTo,1,noun); ];
  1811. [ WaveHandsSub; L__M(##WaveHands,1,noun); ];
  1812. [ BuySub; L__M(##Buy,1,noun); ];
  1813. [ SingSub; L__M(##Sing,1,noun); ];
  1814. [ ClimbSub; L__M(##Climb,1,noun); ];
  1815. [ SleepSub; L__M(##Sleep,1,noun); ];
  1816. [ ConsultSub; L__M(##Consult,1,noun); ];
  1817. [ TouchSub;
  1818.   if (noun==player) return L__M(##Touch,3,noun);
  1819.   if (ObjectIsUntouchable(noun)) return;
  1820.   if (noun has animate) return L__M(##Touch,1,noun);
  1821.   L__M(##Touch,2,noun); ];
  1822. [ WaveSub;
  1823.   if (parent(noun)~=player) return L__M(##Wave,1,noun);
  1824.   L__M(##Wave,2,noun); ];
  1825. [ PullSub;
  1826.   if (ObjectIsUntouchable(noun)) return;
  1827.   if (noun has static)   return L__M(##Pull,1,noun);
  1828.   if (noun has scenery)  return L__M(##Pull,2,noun);
  1829.   if (noun has animate)  return L__M(##Pull,4,noun);
  1830.   L__M(##Pull,3,noun);
  1831. ];
  1832. [ PushSub;
  1833.   if (ObjectIsUntouchable(noun)) return;
  1834.   if (noun has static)   return L__M(##Push,1,noun);
  1835.   if (noun has scenery)  return L__M(##Push,2,noun);
  1836.   if (noun has animate)  return L__M(##Pull,4,noun);
  1837.   L__M(##Push,3,noun);
  1838. ];
  1839. [ TurnSub;
  1840.   if (ObjectIsUntouchable(noun)) return;
  1841.   if (noun has static)   return L__M(##Turn,1,noun);
  1842.   if (noun has scenery)  return L__M(##Turn,2,noun);
  1843.   if (noun has animate)  return L__M(##Pull,4,noun);
  1844.   L__M(##Turn,3,noun);
  1845. ];
  1846.  
  1847. [ WaitSub;
  1848.   if (AfterRoutines()==1) rtrue;
  1849.   L__M(##Wait,1,noun);
  1850. ];
  1851.  
  1852. [ PushDirSub; L__M(##PushDir,1,noun); ];
  1853. [ AllowPushDir i;
  1854.   if (parent(second)~=compass) return L__M(##PushDir,2,noun);
  1855.   if (second==u_obj or d_obj)  return L__M(##PushDir,3,noun);
  1856.   AfterRoutines(); i=noun; move i to player;
  1857.   <Go second>;
  1858.   if (location==thedark) move i to real_location;
  1859.   else move i to location;
  1860. ];
  1861.  
  1862. [ SqueezeSub;
  1863.   if (ObjectIsUntouchable(noun)) return;
  1864.   if (noun has animate) return L__M(##Squeeze,1,noun);
  1865.   L__M(##Squeeze,2,noun);
  1866. ];
  1867.  
  1868. [ ThrowAtSub;
  1869.   if (ObjectIsUntouchable(noun)) return;
  1870.   if (second>1)
  1871.   {   action=##ThrownAt;
  1872.       if (RunRoutines(second,before)~=0) { action=##ThrowAt; rtrue; }
  1873.       action=##ThrowAt;
  1874.   }
  1875.   if (noun has worn)
  1876.   {   L__M(##Drop,3,noun);
  1877.       <Disrobe noun>;
  1878.       if (noun has worn && noun in player) rtrue;
  1879.   }
  1880.   if (second hasnt animate) return L__M(##ThrowAt,1);
  1881.   if (RunLife(second,##ThrowAt)~=0) rfalse;
  1882.   L__M(##ThrowAt,2,noun);
  1883. ];
  1884.  
  1885. [ AttackSub;
  1886.   if (ObjectIsUntouchable(noun)) return;
  1887.   if (noun has animate && RunLife(noun,##Attack)~=0) rfalse;
  1888.   L__M(##Attack,1,noun); ];
  1889.  
  1890. [ KissSub;
  1891.   if (ObjectIsUntouchable(noun)) return;
  1892.   if (RunLife(noun,##Kiss)~=0) rfalse;
  1893.   if (noun==player) return L__M(##Touch,3,noun);
  1894.   L__M(##Kiss,1,noun);
  1895. ];
  1896.  
  1897. [ AnswerSub;
  1898.   if (second~=0 && RunLife(second,##Answer)~=0) rfalse;
  1899.   L__M(##Answer,1,noun);
  1900. ];  
  1901.  
  1902. [ TellSub;
  1903.   if (noun==player) return L__M(##Tell,1,noun);
  1904.   if (RunLife(noun,##Tell)~=0) rfalse;
  1905.   L__M(##Tell,2,noun);
  1906. ];  
  1907.   
  1908. [ AskSub;
  1909.   if (RunLife(noun,##Ask)~=0) rfalse;
  1910.   L__M(##Ask,1,noun);
  1911. ];  
  1912.  
  1913. [ AskForSub;
  1914.   if (noun==player) <<Inv>>;
  1915.   L__M(##Order,1,noun);
  1916. ];
  1917.  
  1918. ! ----------------------------------------------------------------------------
  1919. !   Debugging verbs
  1920. ! ----------------------------------------------------------------------------
  1921.  
  1922. #IFDEF DEBUG;
  1923. [ TraceOnSub; parser_trace=1; "[Trace on.]"; ];
  1924. [ TraceLevelSub; parser_trace=noun;
  1925.   print "[Parser tracing set to level ", parser_trace, ".]^"; ];
  1926. [ TraceOffSub; parser_trace=0; "Trace off."; ];
  1927. [ RoutinesOnSub;  debug_flag=debug_flag | 1; "[Message listing on.]"; ];
  1928. [ RoutinesOffSub; debug_flag=debug_flag & 14; "[Message listing off.]"; ];
  1929. [ ActionsOnSub;  debug_flag=debug_flag | 2; "[Action listing on.]"; ];
  1930. [ ActionsOffSub; debug_flag=debug_flag & 13; "[Action listing off.]"; ];
  1931. [ TimersOnSub;  debug_flag=debug_flag | 4; "[Timers listing on.]"; ];
  1932. [ TimersOffSub; debug_flag=debug_flag & 11; "[Timers listing off.]"; ];
  1933. IFDEF VN_1610;
  1934. [ ChangesOnSub;  debug_flag=debug_flag | 8; "[Changes listing on.]"; ];
  1935. [ ChangesOffSub; debug_flag=debug_flag & 7; "[Changes listing off.]"; ];
  1936. IFNOT;
  1937. [ ChangesOnSub; "[Changes listing only available under Inform 6.2.]"; ];
  1938. [ ChangesOffSub; "[Changes listing only available under Inform 6.2.]"; ];
  1939. ENDIF;
  1940. [ CommandsOnSub;
  1941.   @output_stream 4; xcommsdir=1; "[Command recording on.]"; ];
  1942. [ CommandsOffSub;
  1943.   if (xcommsdir==1) @output_stream -4;
  1944.   xcommsdir=0;
  1945.   "[Command recording off.]"; ];
  1946. [ CommandsReadSub;
  1947.   @input_stream 1; xcommsdir=2; "[Replaying commands.]"; ];
  1948. [ PredictableSub i; i=random(-100);
  1949.   "[Random number generator now predictable.]"; ];
  1950. [ XTestMove obj dest;
  1951.   if ((obj<=InformLibrary) || (obj == LibraryMessages) || (obj in 1))
  1952.      "[Can't move ", (name) obj, ": it's a system object.]";
  1953.   while (dest ~= 0)
  1954.   {   if (dest == obj)
  1955.           "[Can't move ", (name) obj, ": it would contain itself.]";
  1956.       dest = parent(dest);
  1957.   }
  1958.   rfalse;
  1959. ];
  1960. [ XPurloinSub;
  1961.   if (XTestMove(noun,player)) return;
  1962.   move noun to player; give noun moved ~concealed;
  1963.   "[Purloined.]"; ];
  1964. [ XAbstractSub;
  1965.   if (XTestMove(noun,second)) return;
  1966.   move noun to second; "[Abstracted.]"; ];
  1967. [ XObj obj f;
  1968.   if (parent(obj) == 0) print (name) obj; else print (a) obj;
  1969.   print " (", obj, ") ";
  1970.   if (f==1 && parent(obj) ~= 0)
  1971.       print "(in ", (name) parent(obj), " ", parent(obj), ")";
  1972.   new_line;
  1973.   if (child(obj)==0) rtrue;
  1974.   if (obj == Class)
  1975.       WriteListFrom(child(obj),
  1976.       NOARTICLE_BIT + INDENT_BIT + NEWLINE_BIT + ALWAYS_BIT, 1);
  1977.   else
  1978.       WriteListFrom(child(obj),
  1979.       FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + ALWAYS_BIT, 1);
  1980. ];
  1981. [ XTreeSub i;
  1982.   if (noun==0)
  1983.   {   objectloop(i) if (i ofclass Object && parent(i)==0) XObj(i);
  1984.   }
  1985.   else XObj(noun,1);
  1986. ];
  1987. [ GotoSub;
  1988.   if (~~(noun ofclass Object) || (parent(noun)~=0)) "[Not a safe place.]";
  1989.   PlayerTo(noun);
  1990. ];
  1991. [ GonearSub x; x=noun; while (parent(x)~=0) x=parent(x); PlayerTo(x); ];
  1992. [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
  1993. [ ScopeSub; x_scope_count=0; LoopOverScope(#r$Print_ScL, noun);
  1994.   if (x_scope_count==0) "Nothing is in scope.";
  1995. ];
  1996. #ENDIF;
  1997.  
  1998. ! ----------------------------------------------------------------------------
  1999. !   Finally: the mechanism for library text (the text is in the language defn)
  2000. ! ----------------------------------------------------------------------------
  2001.  
  2002. [ L__M act n x1 s;
  2003.   s=sw__var; sw__var=act; if (n==0) n=1;
  2004.   L___M(n,x1);
  2005.   sw__var=s;
  2006. ];
  2007.  
  2008. [ L___M n x1 s;
  2009.   s=action;
  2010.   lm_n=n; lm_o=x1;
  2011.   action=sw__var;
  2012.   if (RunRoutines(LibraryMessages,before)~=0) { action=s; rfalse; }
  2013.   action=s;
  2014.  
  2015.   LanguageLM(n, x1);
  2016. ];
  2017.  
  2018. ! ----------------------------------------------------------------------------
  2019.